using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using elibrary.Classes;
using elibrary.Models;
using elibrary.Models.Entities;

namespace elibrary.Models.Managers
{
	public class BookCategoryManager
	{
		private DataContext ctx;
		private DbSet<BookCategory> bookCategories;

		public BookCategoryManager(DataContext ctx)
		{
			this.ctx = ctx;
			this.bookCategories = ctx.bookCategories;
		}

		public void add(BookCategory bc,bool autoSave=true)
		{
			bookCategories.Add(bc);
			if (autoSave)
				ctx.SaveChanges();
		}

		public BookCategory get(int id)
		{
			return bookCategories.SingleOrDefault(q => q.id == id);
		}

		public BookCategory getByBookCategory(int bid, string cname, int cid=-1)
		{
			if (cid == -1)
			{
				CategoryManager categoryManager = new CategoryManager(ctx);
				var qc = categoryManager.get(cname);

				if (qc == null)
					return null;

				cid = qc.id;
			}

			return bookCategories.SingleOrDefault(q => q.bookId == bid && q.categoryId == cid);
		}

		public List<BookCategory> getAllByCategory(int cid, string cname = null)
		{
			if (!string.IsNullOrWhiteSpace(cname))
			{
				CategoryManager categoryManager = new CategoryManager(ctx);
				Category cat = categoryManager.get(cname);

				if (cat == null)
					return new List<BookCategory>();

				cid = cat.id;
			}

			return Utilities.ensureRs<BookCategory>(bookCategories.Where(
				q => q.categoryId == cid));
		}

		public void delete(int uid,bool autoSave = true)
		{
			delete(get(uid),autoSave);
		}

		public void delete(BookCategory bc,bool autoSave = true)
		{
			if (bc == null)
				return;

			bookCategories.Remove(bc);

			if (autoSave)
				ctx.SaveChanges();
		}

		public void deleteByBook(int bid,string name,bool autoSave = true)
		{
			var r = getAllByBook(bid).Where(q => q.category.name == name);

			if (r != null && r.Any())
			{
				foreach(var item in r)
					bookCategories.Remove(item);

				if (autoSave)
					ctx.SaveChanges();
			}
		}

		public void deleteByBook(int bid,int cid,bool autoSave = true)
		{
			var r = getAllByBook(bid).Where(q => q.categoryId == cid);

			if (r != null && r.Any())
			{
				foreach(var item in r)
					bookCategories.Remove(item);

				if (autoSave)
					ctx.SaveChanges();
			}
		}

		// Take note that this methods always result in changes made to
		// entities auto committed when the method returns.
		public void addForBook(int bid,string name)
		{
			CategoryManager categoryManager = new CategoryManager(AppGlobals.dataContext);
			Category cat = categoryManager.get(name);

			// at creation of new category, prior data changes
			// will be committed to the database. look into ways
			// to mitigate this issue.
			if (cat == null)
			{
				cat.name = name;
				categoryManager.add(cat);
			}

			BookCategory bc = new BookCategory { bookId = bid, categoryId = cat.id };
			this.add(bc);
		}

		public List<BookCategory> getAllByBook(int bid)
		{
			var r = bookCategories.Where(q => q.bookId == bid);

			return r != null && r.Any() ? r.ToList() : new List<BookCategory>();
		}

		public List<BookCategory> getAllByCategory(string cname,int cid=-1)
		{
			IQueryable<BookCategory> r = null;

			if (!string.IsNullOrWhiteSpace(cname))
				r = bookCategories.Where(q => q.category.name.ToLower() == cname.ToLower());
			else
				r = bookCategories.Where(q => q.categoryId == cid);

			return Utilities.ensureRs<BookCategory>(r);
		}

	}
}